/*
 * @Description: 
 * @Version: 
 * @Author: BaiYiZhuo
 * @Date: 2021-11-28 11:28:25
 * @LastEditTime: 2022-01-31 12:26:44
 */
//不带手机控制功能
#include <Arduino.h>
#include <EEPROM.h>
#include <SPI.h>
#include <MFRC522.h>
#include <ESP32Servo.h>
#include <esp_task_wdt.h>

#define RST_PIN 22 // 配置针脚
#define SS_PIN 21
#define servoPIN 25
#define buzzerPin 26
#define saveCardPin 12
#define insideDoor 14

#define WDT_TIMEOUT 3             // 设置看门狗时间3s
MFRC522 mfrc522(SS_PIN, RST_PIN); // 创建新的RFID实例
Servo myservo;                    //创建电机对象
volatile u_int chooseState = 0;   //中断选择 默认0是扫描是否有人读卡

//RC模块使用了D1.D2.D5.D6.D7
/*************************IO配置**************************/
int Buzzer = buzzerPin;     //D0(io16)蜂鸣器，提示音，也可以用led
int btn = saveCardPin;      //D4(io2)按钮，保存门禁卡ID到EEPROM
int insideBtn = insideDoor; //内部开门引脚
/*************************数据**************************/
//使用union结构，合并4个byte数据，转换为1个long
union long_byte
{
    long long_data;
    byte byte_data[4];
};
long_byte lb;
long EEPROM_RFID1 = -1; //EEPROM中保存的门禁卡ID1
long EEPROM_RFID2 = -1;
long EEPROM_RFID3 = -1;
long EEPROM_RFID4 = -1;
long EEPROM_RFID5 = -1;
long EEPROM_RFID6 = -1;
long EEPROM_RFID7 = -1;
long EEPROM_RFID8 = -1;
long EEPROM_RFID9 = -1;
long read_RFID = -1; //当前读取到的门禁卡ID
int num;             //初始化的卡的数量
int address;         //EEPROM 地址

// 新建组件对象
// BlinkerButton Button3("switch1");
// BlinkerButton Button3("switch2");
void opendoor(void)
{
    read_RFID = -1;                        //恢复读取的卡片ID为-1 方便下一次读卡
    int nowServoPosition = myservo.read(); //获取当前门锁状态
    if (nowServoPosition == 180)
    {
        return;
    }
    else
    {
        myservo.write(180);
        delay(2500);
        esp_task_wdt_reset();
        for (int i = 179; i >= 0; i--)
        {
            myservo.write(i);
            delay(10);
            esp_task_wdt_reset();
        }
        // myservo.write(180);
        // esp_task_wdt_reset();
        // delay(1000);
        // esp_task_wdt_reset();
        // delay(1000);
        // myservo.write(120);
        // esp_task_wdt_reset();
        // delay(1000);
        // esp_task_wdt_reset();
        // delay(1000);
        // myservo.write(90);
        // esp_task_wdt_reset();
        // delay(1000);
        // esp_task_wdt_reset();
        // delay(1000);
        // myservo.write(30);
        // esp_task_wdt_reset();
        // delay(1000);
        // esp_task_wdt_reset();
        // myservo.write(0);
        // esp_task_wdt_reset();
        // LightStatusSoundSuccess()
    }
}
//蜂鸣器音效
void Di(int a)
{
    for (int i = 0; i < a; i++)
    {
        digitalWrite(Buzzer, 1);
        delay(500);
        digitalWrite(Buzzer, 0);
        delay(100);
        esp_task_wdt_reset();
    }
}
//内部开门
void insideDoorOpen()
{
    Di(1);
    opendoor();
}
//监听按钮状态，更换显示状态和值
void Btn_Event()
{
    if (read_RFID == -1)
    {
        Serial.println("none card read!");
        Di(3);
    }
    else
    {
        if (!EEPROM.begin(1024))
        {
            Serial.println("failed to initialise EEPROM");
        }
        Serial.println("Switch:" + num);
        esp_task_wdt_reset();
        switch (num)
        {
        case 0:
            address = 0;
            lb.long_data = read_RFID;
            EEPROM_RFID1 = lb.long_data;
            esp_task_wdt_reset();
            EEPROM.writeLong(address, EEPROM_RFID1);
            esp_task_wdt_reset();
            address += sizeof(long);
            Serial.println("ID1 is saving");
            Di(3);
            num = 1;
            EEPROM.writeInt(32, num);
            esp_task_wdt_reset();
            EEPROM.commit(); //执行保存EEPROM
            esp_task_wdt_reset();
            Serial.println("saved!");
            break;
        case 1:
            lb.long_data = read_RFID;
            EEPROM_RFID2 = lb.long_data;
            esp_task_wdt_reset();
            EEPROM.writeLong(address, EEPROM_RFID2);
            esp_task_wdt_reset();
            address += sizeof(long);
            Serial.println("ID2 is saving");
            Di(3);
            num = 2;
            esp_task_wdt_reset();
            EEPROM.writeInt(32, num);
            esp_task_wdt_reset();
            EEPROM.commit(); //执行保存EEPROM
            esp_task_wdt_reset();
            Serial.println("saved!");
            break;

        case 2:
            lb.long_data = read_RFID;
            EEPROM_RFID3 = lb.long_data;
            esp_task_wdt_reset();
            EEPROM.writeLong(address, EEPROM_RFID3);
            esp_task_wdt_reset();
            address += sizeof(long);
            Serial.println("ID3 is saving");
            Di(3);
            num = 3;
            esp_task_wdt_reset();
            EEPROM.writeInt(32, num);
            esp_task_wdt_reset();
            EEPROM.commit(); //执行保存EEPROM
            esp_task_wdt_reset();
            Serial.println("saved!");
            break;
        case 3:
            lb.long_data = read_RFID;
            EEPROM_RFID4 = lb.long_data;
            esp_task_wdt_reset();
            EEPROM.writeLong(address, EEPROM_RFID4);
            address += sizeof(long);
            Serial.println("ID4 is saving");
            Di(3);
            num = 4;
            esp_task_wdt_reset();
            EEPROM.writeInt(32, num);
            esp_task_wdt_reset();
            EEPROM.commit(); //执行保存EEPROM
            esp_task_wdt_reset();
            Serial.println("saved!");
            break;

        case 4:
            lb.long_data = read_RFID;
            EEPROM_RFID5 = lb.long_data;
            esp_task_wdt_reset();
            EEPROM.writeLong(address, EEPROM_RFID5);
            address += sizeof(long);
            Serial.println("ID5 is saving");
            Di(3);
            num = 5;
            esp_task_wdt_reset();
            EEPROM.writeInt(32, num);
            esp_task_wdt_reset();
            EEPROM.commit(); //执行保存EEPROM
            esp_task_wdt_reset();
            Serial.println("saved!");
            break;
        case 5:
            lb.long_data = read_RFID;
            EEPROM_RFID6 = lb.long_data;
            esp_task_wdt_reset();
            EEPROM.writeLong(address, EEPROM_RFID6);
            address += sizeof(long);
            Serial.println("ID6 is saving");
            Di(3);
            num = 6;
            esp_task_wdt_reset();
            EEPROM.writeInt(32, num);
            esp_task_wdt_reset();
            EEPROM.commit(); //执行保存EEPROM
            Serial.println("saved!");
            break;
        case 6:
            lb.long_data = read_RFID;
            EEPROM_RFID7 = lb.long_data;
            esp_task_wdt_reset();
            EEPROM.writeLong(address, EEPROM_RFID7);
            address += sizeof(long);
            Serial.println("ID7 is saving");
            Di(3);
            num = 7;
            esp_task_wdt_reset();
            EEPROM.writeInt(32, num);
            esp_task_wdt_reset();
            EEPROM.commit(); //执行保存EEPROM
            Serial.println("saved!");
            break;

        case 7:
            lb.long_data = read_RFID;
            EEPROM_RFID8 = lb.long_data;
            esp_task_wdt_reset();
            EEPROM.writeLong(address, EEPROM_RFID8);
            address += sizeof(long);
            Serial.println("ID8 is saving");
            Di(3);
            num = 8;
            esp_task_wdt_reset();
            EEPROM.writeInt(32, num);
            esp_task_wdt_reset();
            EEPROM.commit(); //执行保存EEPROM
            Serial.println("saved!");
            break;
        case 8:
            lb.long_data = read_RFID;
            EEPROM_RFID9 = lb.long_data;
            esp_task_wdt_reset();
            EEPROM.writeLong(address, EEPROM_RFID9);
            address += sizeof(long);
            Serial.println("ID9 is saving");
            Di(3);
            num = 9;
            esp_task_wdt_reset();
            EEPROM.writeInt(32, num);
            esp_task_wdt_reset();
            EEPROM.commit(); //执行保存EEPROM
            Serial.println("saved!");
            break;
        default:
            num = 0;
            esp_task_wdt_reset();
            EEPROM.writeInt(32, num);
            esp_task_wdt_reset();
            EEPROM.commit(); //执行保存EEPROM
        }
    }
}

/***********************RFID读卡自定义函数***********************/
//把当前读到卡的ID，对比EEPROM中的ID
void RFID_Handler(long data)
{
    Serial.println(data);

    if (data == EEPROM_RFID1)
    {
        Serial.println("ID1 correct,door wiil open!");
        Di(1);
        opendoor(); //开门函数
    }
    else if (data == EEPROM_RFID2)
    {
        Serial.println("ID2 correct,door wiil open!");
        Di(1);
        opendoor();
    }

    else if (data == EEPROM_RFID3)
    {
        Serial.println("ID3 correct,door wiil open!");
        Di(1);
        opendoor();
    }

    else if (data == EEPROM_RFID4)
    {
        Serial.println("ID4 correct,door wiil open!");
        Di(1);
        opendoor();
    }
    else if (data == EEPROM_RFID5)
    {
        Serial.println("ID5 correct,door wiil open!");
        Di(1);
        opendoor();
    }

    else if (data == EEPROM_RFID6)
    {
        Serial.println("ID6 correct,door wiil open!");
        Di(1);
        opendoor();
    }

    else if (data == EEPROM_RFID7)
    {
        Serial.println("ID7 correct,door wiil open!");
        Di(1);
        opendoor();
    }
    else if (data == EEPROM_RFID8)
    {
        Serial.println("ID8 correct,door wiil open!");
        Di(1);
        opendoor();
    }
    else if (data == EEPROM_RFID9)
    {
        Serial.println("ID9 correct,door wiil open!");
        Di(1);
        opendoor();
    }
    else
    {
        Di(2);
        Serial.println("ID false,dont open!");
        return;
    }
}
//初始化读卡
void RFID_init()
{
    SPI.begin();        // SPI开始
    mfrc522.PCD_Init(); // 初始化
    Serial.println("init readcard!");
}
//用户ID转换类型
long RFID_toLong(byte *by)
{
    long data;
    for (int i = 0; i < 4; i++)
    {
        lb.byte_data[i] = by[i];
    }
    data = lb.long_data;
    return data;
}

//运行读卡
void RFID_read()
{
    if (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial())
    {
        return;
    }
    else
    {
        read_RFID = RFID_toLong(mfrc522.uid.uidByte);
        RFID_Handler(read_RFID);
        mfrc522.PICC_HaltA();      //停止 PICC
        mfrc522.PCD_StopCrypto1(); //停止加密PCD
        return;
    }
}

void interruptAddCard()
{
    chooseState = 1; //添加卡
    while (!digitalRead(btn))
    {
    }
    delay(200);
}
void interruptInSideDoor()
{
    chooseState = 2; //内部开门
    while (!digitalRead(insideBtn))
    {
    }
    delay(200);
}

void setup()
{
    Serial.begin(115200);
    Serial.println("");
    if (!EEPROM.begin(1024))
    {
        Serial.println("failed to initialise EEPROM");
    }
    myservo.attach(servoPIN); //servo.attach():设置舵机数据引脚
    myservo.write(0);         //servo.write():设置转动角度
    //读取EEPROM索引的值            我这里设置了七张卡，不够也可以再加
    int iniaddr = 0;
    EEPROM_RFID1 = EEPROM.readLong(iniaddr);
    Serial.println(EEPROM_RFID1);
    iniaddr += sizeof(long);

    EEPROM_RFID2 = EEPROM.readLong(iniaddr);
    Serial.println(EEPROM_RFID2);
    iniaddr += sizeof(long);

    EEPROM_RFID3 = EEPROM.readLong(iniaddr);
    Serial.println(EEPROM_RFID3);
    iniaddr += sizeof(long);

    EEPROM_RFID4 = EEPROM.readLong(iniaddr);
    Serial.println(EEPROM_RFID4);
    iniaddr += sizeof(long);

    EEPROM_RFID5 = EEPROM.readLong(iniaddr);
    Serial.println(EEPROM_RFID5);
    iniaddr += sizeof(long);

    EEPROM_RFID6 = EEPROM.readLong(iniaddr);
    Serial.println(EEPROM_RFID6);
    iniaddr += sizeof(long);

    EEPROM_RFID7 = EEPROM.readLong(iniaddr);
    Serial.println(EEPROM_RFID7);
    iniaddr += sizeof(long);

    EEPROM_RFID8 = EEPROM.readLong(iniaddr);
    Serial.println(EEPROM_RFID8);
    iniaddr += sizeof(long);

    EEPROM_RFID9 = EEPROM.readLong(iniaddr);
    Serial.println(EEPROM_RFID9);
    num = EEPROM.readInt(32);
    Serial.println("inti ing .....");
    Serial.println("init num is: " + EEPROM.readInt(32));

    pinMode(btn, INPUT_PULLUP); //内部设置nfc上拉引脚

    pinMode(insideBtn, INPUT_PULLUP); //内部开门上拉引脚

    pinMode(Buzzer, OUTPUT); //设置蜂鸣器
    digitalWrite(Buzzer, 0);

    //设置看门狗
    esp_task_wdt_init(WDT_TIMEOUT, true); // Initialize ESP32 Task WDT
    esp_task_wdt_add(NULL);               // Subscribe to the Task WDT

    //绑定中断
    attachInterrupt(digitalPinToInterrupt(insideBtn), interruptInSideDoor, FALLING); //开门中断
    attachInterrupt(digitalPinToInterrupt(btn), interruptAddCard, FALLING);          //加卡中断

    //初始化读卡
    RFID_init();
}

void loop()
{
    switch (chooseState)
    {
    case 0:
    {
        //扫描读卡
        // Serial.println("running....");
        RFID_read(); //读卡并做分析处理
        break;
    }

    case 1:
    {
        Serial.println("添加卡->>>");
        // Serial.print("  中断处理次数为：");
        // Serial.println(count);
        Btn_Event(); //添加卡
        chooseState = 0;
        break;
    }
    case 2:
    {
        Serial.println("内部开门->>>");
        insideDoorOpen(); //内部开门
        chooseState = 0;
        break;
    }
    }
    esp_task_wdt_reset();
}
